package top.lvkun.user.service.impl;

import cn.hutool.http.HttpUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import top.lvkun.basic.constant.Constant;
import top.lvkun.basic.service.impl.BaseServiceImpl;
import top.lvkun.basic.utils.*;
import top.lvkun.org.domain.Employee;
import top.lvkun.org.mapper.EmployeeMapper;
import top.lvkun.user.domain.User;
import top.lvkun.user.domain.UserAddress;
import top.lvkun.user.domain.WxUser;
import top.lvkun.user.domain.dto.AccessTokenDto;
import top.lvkun.user.domain.dto.UserDto;
import top.lvkun.user.domain.dto.UserInfoDto;
import top.lvkun.user.mapper.UserMapper;
import top.lvkun.user.mapper.WxUserMapper;
import top.lvkun.user.service.IUserService;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

@Service
public class UserServiceImpl extends BaseServiceImpl<User> implements IUserService {

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private EmployeeMapper employeeMapper;
    @Autowired
    private WxUserMapper wxUserMapper;

    /**
     * 验证手机号是否注册过
     *
     * @param phone
     * @param type
     * @return
     */
    @Override
    public AjaxResult validatePhone(String phone, String type) {
        User user = userMapper.findByPhone(phone);
        if (Constant.PHONE_REG.equals(type)) {
            //手机号已经被注册
            if (user != null) {
                return AjaxResult.me().setSuccess(false).setMessage("该手机号已经被注册");
            }
        } else if (Constant.PHONE_LOGIN.equals(type)) {
            //登录时，验证该手机号是否已注册
            if (user == null) {
                return AjaxResult.me().setSuccess(false).setMessage("该手机号未被注册,请先注册");
            }
        }
        return AjaxResult.me();
    }

    /**
     * 发送手机短信
     *
     * @param phone
     * @param type  phone_reg表示手机验证码注册，phone_login表示手机验证码登录
     * @return
     */
    @Override
    public AjaxResult sendMobileCode(String type, String phone) {
        //1.随机生成一个验证码
        String verifyCode = StrUtils.getRandomString(6);
        //通过type-phone在redis中查询value
        String value = RedisUtils.INSTANCE.get(type + "-" + phone);
        //当前系统时间
        long currentTime = System.currentTimeMillis();

        if (StringUtils.hasText(value)) {
            //获取上次获取验证码及时间
            verifyCode = value.split("-")[0];
            long lastTime = Long.valueOf(value.split("-")[1]);
            //1分钟内频繁发送
            if (lastTime - currentTime <= 60 * 1000) {
                return AjaxResult.me().setSuccess(false).setMessage("亲，您操作太频繁了！");
            }
            //大于1分钟小于5分钟
            else if (lastTime - currentTime <= 300 * 1000) {
                //重新设置该key的过期时间，并发送之前的相同的短信
                RedisUtils.INSTANCE.set(type + "-" + phone, verifyCode + "-" + currentTime, 300);
                //3.调用短信平台接口，发送短信
                String content = "您注册账户的验证码为：" + verifyCode + "，请在5分钟内完成操作！";
                //SmsUtils.sendCode(phone,content);
                System.out.println("【宠物之家】" + content);
            }

        } else {//首次发送短信，或超过五分钟再发送

            //2.保存到Redis中，设置5分钟后过期，存储格式【 phone_reg-18672000308:123456-46816321523】
            RedisUtils.INSTANCE.set(type + "-" + phone, verifyCode + "-" + currentTime, 300);
            //3.调用短信平台接口，发送短信
            String content = "您注册账户的验证码为：" + verifyCode + "，请在5分钟内完成操作！";
            //SmsUtils.sendCode(phone,content);
            System.out.println("【宠物之家】" + content);

        }
        //4.给前端返回消息
        return AjaxResult.me().setMessage("短信验证码已发送，请在5分钟内完成操作！");

    }

    /**
     * 前台用户注册，提交注册表单
     *
     * @param userDto
     * @return
     */
    @Override
    @Transactional
    public AjaxResult phoneReg(UserDto userDto) {
        if (Constant.PHONE_REG.equals(userDto.getType())) {
            //手机注册
            //先从redis中获取验证码信息
            String value = RedisUtils.INSTANCE.get(userDto.getType() + "-" + userDto.getPhone());
            if (StringUtils.hasText(value)) {
                //获取验证码
                String code = value.split("-")[0];
                if (code.equals(userDto.getVerifyCode())) {
                    userDto.setUsername(userDto.getPhone());
                    userDto.setSalt(StrUtils.getComplexRandomString(32));
                    //用户密码 = 密码+md5（32位验）
                    userDto.setPassword(MD5Utils.encrypByMd5(userDto.getPassword() + userDto.getSalt()));
                    System.out.println(userDto);
                    userMapper.save(userDto);
                    return loginSuccess(userDto);
                    //return AjaxResult.me();
                }
            }
            return AjaxResult.me().setSuccess(false).setMessage("验证码错误");
        } else if (Constant.PHONE_LOGIN.equals(userDto.getType())) {
            //邮箱注册

        }
        return AjaxResult.me().setSuccess(false).setMessage("注册失败！");
    }

    /**
     * 前后台用户登录
     * 1.用户名密码登录
     * 2.短信验证码登录
     *
     * @param userDto
     * @return
     */
    @Override
    public AjaxResult userLogin(UserDto userDto) {
        User user = userMapper.findCountByUser(userDto);
        //前台用户密码登录
        if (Constant.FRONT_LOGIN.equals(userDto.getType())) {
            if (user != null) {
                if (user.getPassword().equals(MD5Utils.encrypByMd5(userDto.getPassword() + user.getSalt()))) {
                   //账号密码登录时判断该账号有没有绑定微信
                    WxUser wxUser = wxUserMapper.loadByUserId(user.getId());
                    if(wxUser!=null){//绑定了微信
                        //将username设置微信的nikename，返回给前端使用
                        user.setUsername(wxUser.getNickname());
                    }
                    return loginSuccess(user);
                }
                return AjaxResult.me().setSuccess(false).setMessage("密码错误");
            }
            return AjaxResult.me().setSuccess(false).setMessage("用户名错误！");
        } else if (Constant.PHONE_LOGIN.equals(userDto.getType())) {
            //前台手机短信登录
            if (user != null) {
                //通过前台传过来的验证码与redis中的验证码比较
                String key = userDto.getType() + "-" + userDto.getPhone();
                String value = RedisUtils.INSTANCE.get(key);
                if (value != null) {
                    value = value.split("-")[0];
                    if (userDto.getVerifyCode().equals(value)) {
                        //删除短信验证码信息
                        RedisUtils.INSTANCE.del(key);
                        return loginSuccess(user);
                    }
                }
                return AjaxResult.me().setSuccess(false).setMessage("验证码错误！");
            }



        } else if (Constant.ADMIN_LOGIN.equals(userDto.getType())) {
            Employee employee = employeeMapper.findByAccount(userDto.getUsername());
            if (employee != null & employee.getState() == Constant.STATE_NORMAL) {
                if (employee.getPassword().equals(MD5Utils.encrypByMd5(userDto.getPassword() + employee.getSalt()))) {
                    return loginSuccess(employee);
                }
                return AjaxResult.me().setSuccess(false).setMessage("密码错误");
            }
            return AjaxResult.me().setSuccess(false).setMessage("用户名错误或账户异常！");

            //微信登录邮箱绑定
        } else if (Constant.EMAILWX.equals(userDto.getType())) {
            //System.out.println("微信登录邮箱绑定执行啦！");
            //1.通过access_token和openid获取用户信息的json对象
            String userinfoUrl = Constant.WECHAT_USERINFO_URL
                    .replace("OPENID", userDto.getOpenid())
                    .replace("ACCESS_TOKEN", userDto.getAccess_token());
            //利用糊涂工具包发送GET请求
            String userinfoStr = HttpUtil.get(userinfoUrl);
            if (!StringUtils.hasText(userinfoStr)) {
                return AjaxResult.me().setSuccess(false).setMessage("用户绑定失败！我们正在殴打程序员....");
            }

            //2.将json字符串转化为实体类对象
            UserInfoDto userInfoDto = JsonUtils.toObj(userinfoStr, UserInfoDto.class);

            //3.保存t_user表信息，返回主键id
            userDto.setSalt(StrUtils.getComplexRandomString(32));
            userDto.setPassword(MD5Utils.encrypByMd5(userDto.getPassword() + userDto.getSalt()));
            userDto.setHeadImg(userInfoDto.getHeadimgurl());
            userMapper.save(userDto);
            //4.保存t_wxuser表信息
            WxUser wxUser = new WxUser();
            wxUser.setOpenid(userInfoDto.getOpenid());
            wxUser.setNickname(userInfoDto.getNickname());
            wxUser.setSex(userInfoDto.getSex());
            wxUser.setAddress(userInfoDto.getCountry() + " " + userInfoDto.getProvince() + " " + userInfoDto.getCity());
            wxUser.setHeadimgurl(userInfoDto.getHeadimgurl());
            wxUser.setUnionid(userInfoDto.getUnionid());
            wxUser.setUser_id(userDto.getId());
            wxUserMapper.save(wxUser);
            //5.执行成代码
            userDto.setUsername(userInfoDto.getNickname());
            return loginSuccess(userDto);
        }else if (Constant.PHONEWX.equals(userDto.getType())) {
            //1.通过access_token和openid获取用户信息的json对象
            String userinfoUrl = Constant.WECHAT_USERINFO_URL
                    .replace("OPENID", userDto.getOpenid())
                    .replace("ACCESS_TOKEN", userDto.getAccess_token());
            //利用糊涂工具包发送GET请求
            String userinfoStr = HttpUtil.get(userinfoUrl);
            if (!StringUtils.hasText(userinfoStr)) {
                return AjaxResult.me().setSuccess(false).setMessage("用户绑定失败！我们正在殴打程序员....");
            }
            //2.将json字符串转化为实体类对象
            UserInfoDto userInfoDto = JsonUtils.toObj(userinfoStr, UserInfoDto.class);
            //3.保存t_user表信息，返回主键id
            userDto.setSalt(StrUtils.getComplexRandomString(32));
            userDto.setPassword(MD5Utils.encrypByMd5(userDto.getPassword() + userDto.getSalt()));
            userDto.setHeadImg(userInfoDto.getHeadimgurl());
            userMapper.save(userDto);
            //4.保存t_wxuser表信息
            WxUser wxUser = new WxUser();
            wxUser.setOpenid(userInfoDto.getOpenid());
            wxUser.setNickname(userInfoDto.getNickname());
            wxUser.setSex(userInfoDto.getSex());
            wxUser.setAddress(userInfoDto.getCountry() + " " + userInfoDto.getProvince() + " " + userInfoDto.getCity());
            wxUser.setHeadimgurl(userInfoDto.getHeadimgurl());
            wxUser.setUnionid(userInfoDto.getUnionid());
            wxUser.setUser_id(userDto.getId());
            wxUserMapper.save(wxUser);
            //5.执行成代码
            userDto.setUsername(userInfoDto.getNickname());
            return loginSuccess(userDto);
        }
        return null;
    }


    /**
     * 通过code获取access_token：利用Java程序发送Http请求获取access_token
     * @param code
     * @return
     */
    @Override
    public AjaxResult wechatLogin(String code) {
        String accessTokenUrl = Constant.ACCESS_TOKEN_URL
                .replace("APPID", Constant.APPID)
                .replace("SECRET", Constant.APPSECRET)
                .replace("CODE", code);

        //利用糊涂工具包发送GET请求
        String result = HttpUtil.get(accessTokenUrl);
        if (!StringUtils.hasText(result)) {
            return AjaxResult.me().setSuccess(false).setMessage("服务器繁忙！");
        }
        //将json字符串转化为实体类对象
        AccessTokenDto accessTokenDto = JsonUtils.toObj(result, AccessTokenDto.class);
        if (!StringUtils.hasText(accessTokenDto.getErrmsg()) && accessTokenDto.getErrcode() == null) {
            //通过openid和unionid去查询t_wxuser表
            WxUser wxUser = wxUserMapper.findByOpenidAndUnionid(accessTokenDto.getOpenid(), accessTokenDto.getUnionid());
            if (wxUser != null) {
                //获取登录用户信息
                User loginUser = wxUser.getUser();
                loginUser.setId(wxUser.getUser_id());
                loginUser.setUsername(wxUser.getNickname());
                return loginSuccess(loginUser);
            }
            //查询不到WxUser数据，表示之前未绑定过，前端应该跳转到绑定页面去
            return AjaxResult.me().setSuccess(false).setMessage("unbind").setData(accessTokenDto);
        }
        return AjaxResult.me().setSuccess(false).setMessage("微信登录失败！" + accessTokenDto.getErrcode() + "---" + accessTokenDto.getErrmsg());
    }

    /**
     * 前台: 查询当前登录用户的地址们
     * @param id
     * @return
     */
    @Override
    public List<UserAddress> getUserAddresses(Long id) {
        return userMapper.getUserAddresses(id);
    }


    /**
     * 抽取登录成功代码
     *
     * @param obj
     * @return
     */
    public AjaxResult loginSuccess(Object obj) {
        //User user
        //随机生成token
        String userToken = UUID.randomUUID().toString();
        //user.setPassword(null);
        //将user对象转换为json对象
        String userJsonStr = JsonUtils.toJsonStr(obj);
        //以userToken为key，json对象为值，并设置过期时间为30存入redis中
        RedisUtils.INSTANCE.set(userToken, userJsonStr, Constant.EXPIRE_TIME_IN_REDIS);
        //最后将token和json对象返回给前端
        Map<String, Object> map = new HashMap<>();
        map.put("userToken", userToken);
        map.put("userJsonStr", userJsonStr);

        return AjaxResult.me().setData(map);
    }
}
